home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / vim / src / memline.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  65KB  |  2,427 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. /* for debugging */
  10. /* #define CHECK(c, s)    if (c) EMSG(s) */
  11. #define CHECK(c, s)
  12.  
  13. /*
  14.  * memline.c: Contains the functions for appending, deleting and changing the
  15.  * text lines. The memfile functions are used to store the information in blocks
  16.  * of memory, backed up by a file. The structure of the information is a tree.
  17.  * The root of the tree is a pointer block. The leaves of the tree are data
  18.  * blocks. In between may be several layers of pointer blocks, forming branches.
  19.  *
  20.  * Three types of blocks are used:
  21.  * - Block nr 0 contains information for recovery
  22.  * - Pointer blocks contain list of pointers to other blocks.
  23.  * - Data blocks contain the actual text.
  24.  *
  25.  * Block nr 0 contains the block0 structure (see below).
  26.  *
  27.  * Block nr 1 is the first pointer block. It is the root of the tree.
  28.  * Other pointer blocks are branches.
  29.  *
  30.  *    If a line is too big to fit in a single page, the block
  31.  *    containing that line is made big enough to hold the line. It may span
  32.  *      several pages. Otherwise all blocks are one page.
  33.  *
  34.  *    A data block that was filled when starting to edit a file and was not
  35.  *      changed since then, can have a negative block number. This means that it
  36.  *      has not yet been assigned a place in the file. When recovering, the lines
  37.  *       in this data block can be read from the original file. When the block is
  38.  *    changed (lines appended/deleted/changd) or when it is flushed it gets
  39.  *    a positive number. Use mf_trans_del() to get the new number, before
  40.  *    calling mf_get().
  41.  */
  42.  
  43. /*
  44.  * The following functions are available to work with a memline:
  45.  * 
  46.  * ml_open()            open a new memline for a buffer
  47.  * ml_close()            close the memline for a buffer
  48.  * ml_close_all()        close all memlines
  49.  * ml_recover()            read a memline for recovery
  50.  * ml_sync_all()        flush changed blocks to file for all files
  51.  * ml_preserve()        flush everything into the file for one file
  52.  * ml_get()                get a pointer to a line
  53.  * ml_get_pos()            get a pointer to a position in a line
  54.  * ml_get_cursor()        get a pointer to the char under the cursor
  55.  * ml_get_buf()            get a pointer to a line in a specific buffer
  56.  * ml_line_alloced()    return TRUE if line was allocated
  57.  * ml_append()            append a new line
  58.  * ml_replace()            replace a line
  59.  * ml_delete()            delete a line
  60.  * ml_setmarked()        set mark for a line (for :global command)
  61.  * ml_firstmarked()        get first line with a mark (for :global command)
  62.  * ml_clearmarked()        clear all line marks (for :global command)
  63.  */
  64.  
  65. #include "vim.h"
  66. #include "globals.h"
  67. #include "proto.h"
  68. #include "param.h"
  69. #include <fcntl.h>
  70.  
  71. #ifdef SASC
  72. # include <proto/dos.h>        /* for Open() and Close() */
  73. #endif
  74.  
  75. typedef struct block0            ZERO_BL;    /* contents of the first block */
  76. typedef struct pointer_block    PTR_BL;        /* contents of a pointer block */
  77. typedef struct data_block        DATA_BL;    /* contents of a data block */
  78. typedef struct pointer_entry    PTR_EN;        /* block/line-count pair */
  79.  
  80. #define DATA_ID    (('d' << 8) + 'a')        /* data block id */
  81. #define PTR_ID    (('p' << 8) + 't')        /* pointer block id */
  82. #define BLOCK0_ID (('b' << 8) + '0')    /* block 0 id */
  83.  
  84. /*
  85.  * pointer to a block, used in a pointer block
  86.  */
  87. struct pointer_entry
  88. {
  89.     blocknr_t    pe_bnum;        /* block number */
  90.     linenr_t    pe_line_count;    /* number of lines in this branch */
  91.     linenr_t    pe_old_lnum;    /* lnum for this block (for recovery) */
  92.     int            pe_page_count;    /* number of pages in block pe_bnum */
  93. };
  94.  
  95. /*
  96.  * A pointer block contains a list of branches in the tree.
  97.  */
  98. struct pointer_block
  99. {
  100.     short_u        pb_id;            /* id for pointer block: PBL_ID */
  101.     short_u        pb_count;        /* number of pointer in this block */
  102.     short_u        pb_count_max;    /* maximum value for pb_count */
  103.     PTR_EN        pb_pointer[1];    /* list of pointers to blocks (actually longer)
  104.                                  * followed by empty space until end of page */
  105. };
  106.  
  107. /*
  108.  * A data block is a leaf in the tree.
  109.  *
  110.  * The text of the lines is at the end of the block. The text of the first line
  111.  * in the block is put at the end, the text of the second line in front of it,
  112.  * etc. Thus the order of the lines is the opposite of the line number.
  113.  */
  114. struct data_block
  115. {
  116.     short_u        db_id;            /* id for data block: DBL_ID */
  117.     unsigned    db_free;        /* free space available */
  118.     unsigned    db_txt_start;    /* byte where text starts */
  119.     unsigned    db_txt_end;        /* byte just after data block */
  120.     linenr_t    db_line_count;    /* number of lines in this block */
  121.     unsigned    db_index[1];    /* index for start of line (actually bigger)
  122.                                  * followed by empty space upto db_txt_start
  123.                                  * followed by the text in the lines until
  124.                                  * end of page */
  125. };
  126.  
  127. /*
  128.  * The low bits of db_index hold the actual index. The topmost bit is
  129.  * used for the global command to be able to mark a line. 
  130.  * This method is not clean, but otherwise there would be at least one extra
  131.  * byte used for each line.
  132.  * The mark has to be in this place to keep it with the correct line when other
  133.  * lines are inserted or deleted.
  134.  */
  135. #define DB_MARKED        (1 << ((sizeof(unsigned) * 8) - 1))
  136. #define DB_INDEX_MASK    (~DB_MARKED)
  137.  
  138. #define INDEX_SIZE    (sizeof(unsigned))        /* size of one db_index entry */
  139. #define HEADER_SIZE    (sizeof(DATA_BL) - INDEX_SIZE)    /* size of data block header */
  140.  
  141. struct block0
  142. {
  143.     short_u        b0_id;            /* id for block 0: BLOCK0_ID */
  144.     char_u        b0_version[10];    /* Vim version string */
  145.     int            b0_page_size;    /* number of bytes per page */
  146.     long        b0_mtime;        /* last modification time of file */
  147.     char_u        b0_fname[1000];    /* file name of file being edited */
  148. };
  149.  
  150. /* NOTE: if size of block0 changes, adjust minimal block size in mf_open()!! */
  151.  
  152. #define STACK_INCR        5        /* number of entries added to ml_stack at a time */
  153.  
  154. /*
  155.  * The line number where the first mark may be is remembered.
  156.  * If it is 0 there are no marks at all.
  157.  * (always used for the current buffer only, no buffer change possible while
  158.  * executing a global command).
  159.  */
  160. static linenr_t    lowest_marked = 0;
  161.  
  162. /*
  163.  * arguments for ml_find_line()
  164.  */
  165. #define ML_DELETE        0x11        /* delete line */
  166. #define ML_INSERT        0x12        /* insert line */
  167. #define ML_FIND            0x13        /* just find the line */
  168. #define ML_FLUSH        0x02        /* flush locked block */
  169. #define ML_SIMPLE(x)    (x & 0x10)    /* DEL, INS or FIND */
  170.  
  171. static int ml_append_int __ARGS((BUF *, linenr_t, char_u *, colnr_t, int));
  172. static int ml_delete_int __ARGS((BUF *, linenr_t));
  173. static char_u *findswapname __ARGS((BUF *, int));
  174. static void ml_flush_line __ARGS((BUF *));
  175. static BHDR *ml_new_data __ARGS((MEMFILE *, int, int));
  176. static BHDR *ml_new_ptr __ARGS((MEMFILE *));
  177. static BHDR *ml_find_line __ARGS((BUF *, linenr_t, int));
  178. static int ml_add_stack __ARGS((BUF *));
  179. static char_u *makeswapname __ARGS((BUF *, int));
  180. static void ml_lineadd __ARGS((BUF *, int));
  181.  
  182. /*
  183.  * open a new memline for 'curbuf'
  184.  *
  185.  * return FAIL for failure, OK otherwise
  186.  */
  187.     int
  188. ml_open()
  189. {
  190.     MEMFILE        *mfp = NULL;
  191.     char_u        *fname = NULL;
  192.     BHDR        *hp = NULL;
  193.     ZERO_BL        *b0p;
  194.     struct stat    st;
  195.     int            i;
  196.  
  197. /*
  198.  * init fields in memline struct
  199.  */
  200.     curbuf->b_ml.ml_stack_size = 0;        /* no stack yet */
  201.     curbuf->b_ml.ml_stack = NULL;        /* no stack yet */
  202.     curbuf->b_ml.ml_stack_top = 0;        /* nothing in the stack */
  203.     curbuf->b_ml.ml_locked = NULL;        /* no cached block */
  204.     curbuf->b_ml.ml_line_lnum = 0;        /* no cached line */
  205.  
  206. /*
  207.  * make fname for swap file
  208.  * If we are unable to find a file name, mf_fname will be NULL
  209.  * and the memfile will be in memory only (no recovery possible).
  210.  * When 'updatecount' is 0 there is never a swap file.
  211.  */
  212.     if (p_uc == 0)
  213.         fname = NULL;
  214.     else
  215.         fname = findswapname(curbuf, FALSE);        /* NULL detected below */
  216.  
  217. /*
  218.  * open the memfile
  219.  *
  220.  * If a file name given, 'directory' option is set and does not start with '>'
  221.  * may try twice: first in current dir and if that fails in 'directory'.
  222.  */
  223.     if (fname != NULL && *p_dir != NUL && *p_dir != '>')
  224.         i = 0;        /* try twice */
  225.     else
  226.         i = 1;        /* try once */
  227.     for ( ; i < 2 && (mfp = mf_open(fname, TRUE, i == 0)) == NULL; ++i)
  228.     {
  229.         fname = findswapname(curbuf, TRUE);        /* NULL detected below */
  230.     }
  231.     if (mfp == NULL)
  232.         goto error;
  233.     curbuf->b_ml.ml_mfp = mfp;
  234.     curbuf->b_neverloaded = FALSE;
  235.     if (p_uc != 0 && mfp->mf_fname == NULL)
  236.     {
  237.                 /* call wait_return if not done by emsg() */
  238.         if (EMSG("Unable to open swap file, recovery impossible"))
  239.         {
  240.             msg_outchar('\n');
  241.             wait_return(FALSE);
  242.         }
  243.     }
  244.  
  245. /*
  246.  * fill block0 struct and write page 0
  247.  */
  248.     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
  249.         goto error;
  250.     if (hp->bh_bnum != 0)
  251.     {
  252.         EMSG("didn't get block nr 0?");
  253.         goto error;
  254.     }
  255.     b0p = (ZERO_BL *)(hp->bh_data);
  256.     b0p->b0_id = BLOCK0_ID;
  257.     STRNCPY(b0p->b0_version, Version, (size_t)10);
  258.     if (curbuf->b_filename != NULL)
  259.     {
  260.         STRNCPY(b0p->b0_fname, curbuf->b_filename, (size_t)1000);
  261.         if (stat((char *)curbuf->b_filename, &st) != -1)
  262.             b0p->b0_mtime = st.st_mtime;
  263.         else
  264.             b0p->b0_mtime = 0;
  265.     }
  266.     else
  267.         b0p->b0_fname[0] = NUL;
  268.     b0p->b0_page_size = mfp->mf_page_size;
  269.     mf_put(mfp, hp, TRUE, FALSE);
  270.  
  271. /*
  272.  * fill in root pointer block and write page 1
  273.  */
  274.     if ((hp = ml_new_ptr(mfp)) == NULL)
  275.         goto error;
  276.     if (hp->bh_bnum != 1)
  277.     {
  278.         EMSG("didn't get block nr 1?");
  279.         goto error;
  280.     }
  281.     mf_put(mfp, hp, TRUE, FALSE);
  282.     curbuf->b_ml.ml_flags = ML_EMPTY;
  283.  
  284.     return OK;
  285.  
  286. error:
  287.     if (mfp != NULL)
  288.     {
  289.         if (hp)
  290.             mf_put(mfp, hp, FALSE, FALSE);
  291.         mf_close(mfp, TRUE);        /* will also free(fname) */
  292.     }
  293.     else
  294.         free(fname);
  295.     curbuf->b_ml.ml_mfp = NULL;
  296.     return FAIL;
  297. }
  298.  
  299. /*
  300.  * Open a file for the memfile for all buffers.
  301.  * Used when 'updatecount' changes from zero to non-zero.
  302.  */
  303.     void
  304. ml_open_files()
  305. {
  306.     BUF            *buf;
  307.     MEMFILE        *mfp;
  308.     char_u        *fname;
  309.     int            i;
  310.  
  311.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  312.     {
  313.         mfp = buf->b_ml.ml_mfp;
  314.         if (mfp == NULL || mfp->mf_fd >= 0)            /* nothing to do */
  315.             continue;
  316.  
  317.     /*
  318.      * make fname for swap file
  319.      * If we are unable to find a file name, mf_fname will be NULL
  320.      * and the memfile will remain in memory only (no recovery possible).
  321.      */
  322.         fname = findswapname(buf, FALSE);        /* NULL detected below */
  323.  
  324.     /*
  325.      * open the memfile
  326.      *
  327.      * If a file name given, 'directory' option is set and does not start with '>'
  328.      * may try twice: first in current dir and if that fails in 'directory'.
  329.      */
  330.         if (fname != NULL && *p_dir != NUL && *p_dir != '>')
  331.             i = 0;        /* try twice */
  332.         else
  333.             i = 1;        /* try once */
  334.         for ( ; i < 2 && mf_open_file(mfp, fname) == FAIL; ++i)
  335.         {
  336.             fname = findswapname(buf, TRUE);        /* NULL detected below */
  337.         }
  338.         if (mfp->mf_fname == NULL)
  339.         {
  340.                     /* call wait_return if not done by emsg() */
  341.             if (EMSG2("Unable to open swap file for \"%s\", recovery impossible",
  342.                     buf->b_xfilename == NULL ? (char_u *)"No File"
  343.                                              : buf->b_xfilename))
  344.             {
  345.                 msg_outchar('\n');
  346.                 wait_return(FALSE);
  347.             }
  348.         }
  349.     }
  350. }
  351.  
  352. /*
  353.  * close memline for buffer 'buf' and delete the swap file
  354.  */
  355.     void
  356. ml_close(buf)
  357.     BUF        *buf;
  358. {
  359.     if (buf->b_ml.ml_mfp == NULL)                /* not open */
  360.         return;
  361.     mf_close(buf->b_ml.ml_mfp, TRUE);            /* delete the .swp file */
  362.     if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY))
  363.         free(buf->b_ml.ml_line_ptr);
  364.     free(buf->b_ml.ml_stack);
  365.     buf->b_ml.ml_mfp = NULL;
  366. }
  367.  
  368. /*
  369.  * Close all existing memlines and memfiles.
  370.  * Used when exiting.
  371.  */
  372.     void
  373. ml_close_all()
  374. {
  375.     BUF        *buf;
  376.  
  377.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  378.         ml_close(buf);
  379. }
  380.  
  381. /*
  382.  * Update the timestamp in the .swp file.
  383.  * Used when the file has been written.
  384.  */
  385.     void
  386. ml_timestamp(buf)
  387.     BUF            *buf;
  388. {
  389.     MEMFILE        *mfp = NULL;
  390.     BHDR        *hp = NULL;
  391.     ZERO_BL        *b0p;
  392.     struct stat    st;
  393.  
  394.     mfp = buf->b_ml.ml_mfp;
  395.  
  396.     if (mfp == NULL || (hp = mf_get(mfp, (blocknr_t)0, 1)) == NULL)
  397.         return;
  398.     b0p = (ZERO_BL *)(hp->bh_data);
  399.     if (b0p->b0_id != BLOCK0_ID)
  400.     {
  401.         EMSG("ml_timestamp: Didn't get block 0??");
  402.         goto error;
  403.     }
  404.         /* copy filename again, it may have been changed */
  405.     STRNCPY(b0p->b0_fname, buf->b_filename, (size_t)1000);
  406.     if (stat((char *)buf->b_filename, &st) != -1)
  407.         b0p->b0_mtime = st.st_mtime;
  408. error:
  409.     mf_put(mfp, hp, TRUE, FALSE);
  410. }
  411.  
  412. /*
  413.  * try to recover curbuf from the .swp file
  414.  */
  415.     void
  416. ml_recover()
  417. {
  418.     BUF            *buf = NULL;
  419.     MEMFILE        *mfp = NULL;
  420.     char_u        *fname = NULL;
  421.     BHDR        *hp = NULL;
  422.     ZERO_BL        *b0p;
  423.     PTR_BL        *pp;
  424.     DATA_BL        *dp;
  425.     IPTR        *ip;
  426.     blocknr_t    bnum;
  427.     int            page_count;
  428.     struct stat    org_stat, swp_stat;
  429.     int            len;
  430.     int            directly;
  431.     linenr_t    lnum;
  432.     char_u        *p;
  433.     int            i;
  434.     long        error;
  435.     int            cannot_open;
  436.     linenr_t    line_count;
  437.     int            has_error;
  438.     int            idx;
  439.     int            top;
  440.     int            txt_start;
  441.     long        size;
  442.  
  443. /*
  444.  * If the file name ends in ".sw?" we use it directly.
  445.  * Otherwise ".swp" is appended.
  446.  */
  447.     fname = curbuf->b_xfilename;
  448.     len = STRLEN(fname);
  449.     if (len >= 4 && vim_strnicmp(fname + len - 4, (char_u *)".sw", (size_t)3) == 0)
  450.     {
  451.         fname = strsave(fname);        /* make a copy for mf_open */
  452.         directly = TRUE;
  453.     }
  454.     else
  455.     {
  456.         fname = makeswapname(curbuf, FALSE);
  457.         directly = FALSE;
  458.     }
  459.     if (fname == NULL)
  460.         goto theend;                    /* out of memory */
  461.  
  462. /*
  463.  * allocate a buffer structure (only the memline in it is really used)
  464.  */
  465.     buf = (BUF *)alloc((unsigned)sizeof(BUF));
  466.     if (buf == NULL)
  467.         goto theend;
  468.  
  469. /*
  470.  * init fields in memline struct
  471.  */
  472.     buf->b_ml.ml_stack_size = 0;        /* no stack yet */
  473.     buf->b_ml.ml_stack = NULL;            /* no stack yet */
  474.     buf->b_ml.ml_stack_top = 0;            /* nothing in the stack */
  475.     buf->b_ml.ml_line_lnum = 0;            /* no cached line */
  476.     buf->b_ml.ml_locked = NULL;            /* no locked block */
  477.     buf->b_ml.ml_flags = 0;
  478.  
  479. /*
  480.  * open the memfile
  481.  *
  482.  * If swap file name not given directly, 'directory' option is set and
  483.  * does not start with '>' may try twice: first in current dir and if that
  484.  * fails in 'directory'.
  485.  */
  486.     if (!directly && *p_dir != NUL && *p_dir != '>')
  487.         i = 0;        /* try twice */
  488.     else
  489.         i = 1;        /* try once */
  490.     for ( ; i < 2 && (mfp = mf_open(fname, FALSE, i == 0)) == NULL; i++)
  491.     {
  492.         fname = makeswapname(curbuf, TRUE);
  493.         if (fname == NULL)
  494.             goto theend;
  495.     }
  496.     if (mfp == NULL || mfp->mf_fd < 0)
  497.     {
  498.         EMSG2("Cannot open %s", fname);
  499.         goto theend;
  500.     }
  501.     buf->b_ml.ml_mfp = mfp;
  502.  
  503. /*
  504.  * try to read block 0
  505.  */
  506.     if ((hp = mf_get(mfp, (blocknr_t)0, 1)) == NULL)
  507.     {
  508.         msg_start();
  509.         msg_outstr((char_u *)"Unable to read block 0 from ");
  510.         msg_outstr(fname);
  511.         msg_outstr((char_u *)"\nMaybe no changes were made or Vim did not update the .swp file");
  512.         msg_end();
  513.         goto theend;
  514.     }
  515.     b0p = (ZERO_BL *)(hp->bh_data);
  516.     if (b0p->b0_id != BLOCK0_ID)
  517.     {
  518.         EMSG2("%s is not a swap file", fname);
  519.         goto theend;
  520.     }
  521.     /*
  522.      * If we guessed the wrong page size, we have to recalculate the
  523.      * hightest block number in the file
  524.      */
  525.     if (mfp->mf_page_size != b0p->b0_page_size)
  526.     {
  527.         mfp->mf_page_size = b0p->b0_page_size;
  528.         if ((size = lseek(mfp->mf_fd, 0L, SEEK_END)) <= 0)
  529.             mfp->mf_blocknr_max = 0;        /* no file or empty file */
  530.         else
  531.             mfp->mf_blocknr_max = size / mfp->mf_page_size;
  532.         mfp->mf_infile_count = mfp->mf_blocknr_max;
  533.     }
  534.  
  535. /*
  536.  * If .swp file name given directly, use name from swap file for buffer
  537.  */
  538.     if (directly && setfname(b0p->b0_fname, NULL, TRUE) == FAIL)
  539.         goto theend;
  540.  
  541.     smsg((char_u *)"Using swap file \"%s\", original file \"%s\"", fname,
  542.                 curbuf->b_filename == NULL ? "No File" : (char *)curbuf->b_filename);
  543.  
  544. /*
  545.  * check date of swap file and original file
  546.  */
  547.     if (curbuf->b_filename != NULL &&
  548.             stat((char *)curbuf->b_filename, &org_stat) != -1 &&
  549.             ((stat((char *)fname, &swp_stat) != -1 &&
  550.             org_stat.st_mtime > swp_stat.st_mtime) ||
  551.             org_stat.st_mtime != b0p->b0_mtime))
  552.     {
  553.         MSG("Warning: Original file may have been changed");
  554.     }
  555.     mf_put(mfp, hp, FALSE, FALSE);        /* release block 0 */
  556.     hp = NULL;
  557.  
  558.     bnum = 1;            /* start with block 1 */
  559.     page_count = 1;        /* which is 1 page */
  560.     lnum = 0;            /* append after line 0 in curbuf */
  561.     line_count = 0;
  562.     idx = 0;            /* start with first index in block 1 */
  563.     error = 0;
  564.     buf->b_ml.ml_stack_top = 0;
  565.     buf->b_ml.ml_stack = NULL;
  566.     buf->b_ml.ml_stack_size = 0;        /* no stack yet */
  567.  
  568.     if (curbuf->b_filename == NULL)
  569.         cannot_open = TRUE;
  570.     else
  571.         cannot_open = FALSE;
  572.  
  573.     for (;;)
  574.     {
  575.         if ((lnum & 15) == 0)        /* check for interrupt now and then */
  576.         {
  577.             breakcheck();
  578.             if (got_int)
  579.                 break;
  580.         }
  581.  
  582.         if (hp != NULL)
  583.             mf_put(mfp, hp, FALSE, FALSE);        /* release previous block */
  584.  
  585.         /*
  586.          * get block
  587.          */
  588.         if ((hp = mf_get(mfp, (blocknr_t)bnum, page_count)) == NULL)
  589.         {
  590.             if (bnum == 1)
  591.             {
  592.                 EMSG2("Unable to read block 1 from %s", fname);
  593.                 goto theend;
  594.             }
  595.             ++error;
  596.             ml_append(lnum++, (char_u *)"???MANY LINES MISSING", (colnr_t)0, TRUE);
  597.         }
  598.         else            /* there is a block */
  599.         {
  600.             pp = (PTR_BL *)(hp->bh_data);
  601.             if (pp->pb_id == PTR_ID)        /* it is a pointer block */
  602.             {
  603.                     /* check line count when using pointer block first time */
  604.                 if (idx == 0 && line_count != 0)
  605.                 {
  606.                     for (i = 0; i < (int)pp->pb_count; ++i)
  607.                         line_count -= pp->pb_pointer[i].pe_line_count;
  608.                     if (line_count != 0)
  609.                     {
  610.                         ++error;
  611.                         ml_append(lnum++, (char_u *)"???LINE COUNT WRONG", (colnr_t)0, TRUE);
  612.                     }
  613.                 }
  614.  
  615.                 if (pp->pb_count == 0)
  616.                 {
  617.                     ml_append(lnum++, (char_u *)"???EMPTY BLOCK", (colnr_t)0, TRUE);
  618.                     ++error;
  619.                 }
  620.                 else if (idx < (int)pp->pb_count)        /* go a block deeper */
  621.                 {
  622.                     if (pp->pb_pointer[idx].pe_bnum < 0)
  623.                     {
  624.                         /*
  625.                          * data block with negative block number
  626.                          *                Try to read lines from the original file.
  627.                          * This is slow, but it works.
  628.                          */
  629.                         if (!cannot_open)
  630.                         {
  631.                             line_count = pp->pb_pointer[idx].pe_line_count;
  632.                             if (readfile(curbuf->b_filename, NULL, lnum, FALSE,
  633.                                         pp->pb_pointer[idx].pe_old_lnum - 1,
  634.                                         line_count) == FAIL)
  635.                                 cannot_open = TRUE;
  636.                             else
  637.                                 lnum += line_count;
  638.                         }
  639.                         if (cannot_open)
  640.                         {
  641.                             ++error;
  642.                             ml_append(lnum++, (char_u *)"???LINES MISSING", (colnr_t)0, TRUE);
  643.                         }
  644.                         ++idx;        /* get same block again for next index */
  645.                         continue;
  646.                     }
  647.  
  648.                     /*
  649.                      * going one block deeper in the tree
  650.                      */
  651.                     if ((top = ml_add_stack(buf)) < 0)        /* new entry in stack */
  652.                     {
  653.                         ++error;
  654.                         break;                /* out of memory */
  655.                     }
  656.                     ip = &(buf->b_ml.ml_stack[top]);
  657.                     ip->ip_bnum = bnum;
  658.                     ip->ip_index = idx;
  659.  
  660.                     bnum = pp->pb_pointer[idx].pe_bnum;
  661.                     line_count = pp->pb_pointer[idx].pe_line_count;
  662.                     page_count = pp->pb_pointer[idx].pe_page_count;
  663.                     continue;
  664.                 }
  665.             }
  666.             else            /* not a pointer block */
  667.             {
  668.                 dp = (DATA_BL *)(hp->bh_data);
  669.                 if (dp->db_id != DATA_ID)        /* block id wrong */
  670.                 {
  671.                     if (bnum == 1)
  672.                     {
  673.                         EMSG2("Block 1 ID wrong (%s not a .swp file?)", fname);
  674.                         goto theend;
  675.                     }
  676.                     ++error;
  677.                     ml_append(lnum++, (char_u *)"???BLOCK MISSING", (colnr_t)0, TRUE);
  678.                 }
  679.                 else
  680.                 {
  681.                     /*
  682.                      * it is a data block
  683.                      * Append all the lines in this block
  684.                      */
  685.                     has_error = FALSE;
  686.                         /*
  687.                          * check length of block
  688.                          * if wrong, use length in pointer block
  689.                          */
  690.                     if (page_count * mfp->mf_page_size != dp->db_txt_end)
  691.                     {
  692.                         ml_append(lnum++, (char_u *)"???until END lines may be messed up", (colnr_t)0, TRUE);
  693.                         ++error;
  694.                         has_error = TRUE;
  695.                         dp->db_txt_end = page_count * mfp->mf_page_size;
  696.                     }
  697.                         
  698.                         /* make sure there is a NUL at the end of the block */
  699.                     *((char_u *)dp + dp->db_txt_end - 1) = NUL;
  700.  
  701.                         /*
  702.                          * check number of lines in block
  703.                          * if wrong, use count in data block
  704.                          */
  705.                     if (line_count != dp->db_line_count)
  706.                     {
  707.                         ml_append(lnum++, (char_u *)"???until END lines may have been inserted/deleted", (colnr_t)0, TRUE);
  708.                         ++error;
  709.                         has_error = TRUE;
  710.                     }
  711.  
  712.                     for (i = 0; i < dp->db_line_count; ++i)
  713.                     {
  714.                         txt_start = (dp->db_index[i] & DB_INDEX_MASK);
  715.                         if (txt_start <= HEADER_SIZE || txt_start >= (int)dp->db_txt_end)
  716.                         {
  717.                             p = (char_u *)"???";
  718.                             ++error;
  719.                         }
  720.                         else
  721.                             p = (char_u *)dp + txt_start;
  722.                         ml_append(lnum++, p, (colnr_t)0, TRUE);
  723.                     }
  724.                     if (has_error)
  725.                         ml_append(lnum++, (char_u *)"???END", (colnr_t)0, TRUE);
  726.                 }
  727.             }
  728.         }
  729.  
  730.         if (buf->b_ml.ml_stack_top == 0)        /* finished */
  731.             break;
  732.  
  733.         /*
  734.          * go one block up in the tree
  735.          */
  736.         ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]);
  737.         bnum = ip->ip_bnum;
  738.         idx = ip->ip_index + 1;        /* go to next index */
  739.         page_count = 1;
  740.     }
  741.  
  742.     recoverymode = 0;
  743.     if (got_int)
  744.         EMSG("Recovery Interrupted");
  745.     else if (error)
  746.         EMSG("Errors detected while recovering; look for lines starting with ???");
  747.     else
  748.         MSG("Recovery completed; If everything is OK: Save this file and delete the .swp file");
  749.  
  750. theend:
  751.     if (mfp != NULL)
  752.     {
  753.         if (hp != NULL)
  754.             mf_put(mfp, hp, FALSE, FALSE);
  755.         mf_close(mfp, FALSE);        /* will also free(fname) */
  756.     }
  757.     else
  758.         free(fname);
  759.     free(buf);
  760.     return;
  761. }
  762.  
  763. /*
  764.  * sync all memlines
  765.  *
  766.  * Stop syncing when character becomes available, but always sync at
  767.  * least one block.
  768.  * If 'check_file' is TRUE, check if original file exists and was not changed.
  769.  */
  770.     void
  771. ml_sync_all(check_file)
  772.     int        check_file;
  773. {
  774.     BUF                *buf;
  775.     struct stat        st;
  776.  
  777.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  778.     {
  779.         if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL)
  780.             continue;                        /* no file */
  781.  
  782.         ml_flush_line(buf);                                /* flush buffered line */
  783.         (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);    /* flush locked block */
  784.         if (buf->b_changed && check_file && mf_need_trans(buf->b_ml.ml_mfp) &&
  785.                                     buf->b_filename != NULL)
  786.         {
  787.             /*
  788.              * if original file does not exist anymore or has been changed
  789.              * call ml_preserve to get rid of all negative numbered blocks
  790.              */
  791.             if (stat((char *)buf->b_filename, &st) == -1 ||
  792.                                 st.st_mtime != buf->b_mtime)
  793.                 ml_preserve(buf, FALSE);
  794.         }
  795.         if (buf->b_ml.ml_mfp->mf_dirty)
  796.         {
  797.             mf_sync(buf->b_ml.ml_mfp, FALSE, TRUE);
  798.             if (mch_char_avail())            /* character available now */
  799.                 break;
  800.         }
  801.     }
  802. }
  803.  
  804. /*
  805.  * sync one buffer, including negative blocks
  806.  *
  807.  * after this all the blocks are in the swap file
  808.  *
  809.  * Used for the :preserve command and when the original file has been
  810.  * changed or deleted.
  811.  *
  812.  * when message is TRUE the success of preserving is reported
  813.  */
  814.     void
  815. ml_preserve(buf, message)
  816.     BUF        *buf;
  817.     int        message;
  818. {
  819.     BHDR        *hp;
  820.     linenr_t    lnum;
  821.     MEMFILE        *mfp = buf->b_ml.ml_mfp;
  822.     int            status;
  823.  
  824.     if (mfp == NULL || mfp->mf_fname == NULL)
  825.     {
  826.         if (message)
  827.             EMSG("Cannot preserve, there is no swap file");
  828.         return;
  829.     }
  830.  
  831.     ml_flush_line(buf);                                /* flush buffered line */
  832.     (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);    /* flush locked block */
  833.     status = mf_sync(mfp, TRUE, FALSE);
  834.         
  835.             /* stack is invalid after mf_sync(.., TRUE, ..) */
  836.     buf->b_ml.ml_stack_top = 0;
  837.  
  838.     /*
  839.      * Some of the data blocks may have been changed from negative to
  840.      * positive block number. In that case the pointer blocks need to be updated.
  841.      *
  842.      * We don't know in which pointer block the references are, so we visit
  843.      * all data blocks until there are no more translations to be done.
  844.      * ml_find_line() does the work by translating the negative block numbers
  845.      * when getting the first line of each data block.
  846.      */
  847.     if (mf_need_trans(mfp))
  848.     {
  849.         lnum = 1;
  850.         while (mf_need_trans(mfp))
  851.         {
  852.             hp = ml_find_line(buf, lnum, ML_FIND);
  853.             if (hp == NULL)
  854.             {
  855.                 status = FAIL;
  856.                 goto theend;
  857.             }
  858.             CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
  859.             lnum = buf->b_ml.ml_locked_high + 1;
  860.         }
  861.         (void)ml_find_line(buf, (linenr_t)0, ML_FLUSH);    /* flush locked block */
  862.         if (mf_sync(mfp, TRUE, FALSE) == FAIL)    /* sync the updated pointer blocks */
  863.             status = FAIL;
  864.         buf->b_ml.ml_stack_top = 0;            /* stack is invalid now */
  865.     }
  866. theend:
  867.     if (message)
  868.     {
  869.         if (status == OK)
  870.             MSG("File preserved");
  871.         else
  872.             EMSG("Preserve failed");
  873.     }
  874. }
  875.  
  876. /*
  877.  * get a pointer to a (read-only copy of a) line 
  878.  * 
  879.  * On failure an error message is given and IObuff is returned (to avoid
  880.  * having to check for error everywhere).
  881.  */
  882.     char_u    *
  883. ml_get(lnum)
  884.     linenr_t    lnum;
  885. {
  886.     return ml_get_buf(curbuf, lnum, FALSE);
  887. }
  888.  
  889. /*
  890.  * ml_get_pos: get pointer to position 'pos'
  891.  */
  892.     char_u *
  893. ml_get_pos(pos)
  894.     FPOS    *pos;
  895. {
  896.     return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col);
  897. }
  898.  
  899.     char_u *
  900. ml_get_cursor()
  901. {
  902.     return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) + curwin->w_cursor.col);
  903. }
  904.  
  905. /*
  906.  * get a pointer to a line in a specific buffer
  907.  *
  908.  *  will_change: if TRUE mark the buffer dirty (chars in the line will be changed)
  909.  */
  910.     char_u    *
  911. ml_get_buf(buf, lnum, will_change)
  912.     BUF            *buf;
  913.     linenr_t    lnum;
  914.     int            will_change;        /* line will be changed */
  915. {
  916.     BHDR    *hp;
  917.     DATA_BL    *dp;
  918.     char_u    *ptr;
  919.  
  920.     if (lnum < 1 || lnum > buf->b_ml.ml_line_count)        /* invalid line number */
  921.     {
  922.         emsg2((char_u *)"ml_get: invalid lnum: %ld", (char_u *)lnum);
  923. errorret:
  924.         STRCPY(IObuff, "???");
  925.         return IObuff;
  926.     }
  927.  
  928. /*
  929.  * See if it is the same line as requested last time.
  930.  * Otherwise may need to flush last used line.
  931.  */
  932.     if (buf->b_ml.ml_line_lnum != lnum)
  933.     {
  934.         ml_flush_line(buf);
  935.  
  936.         if (buf->b_ml.ml_flags & ML_EMPTY)                    /* empty buffer */
  937.             return (char_u *)"";
  938.  
  939.         /*
  940.          * find the data block containing the line
  941.          * This also fills the stack with the blocks from the root to the data block
  942.          * This also releases any locked block.
  943.          */
  944.         if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL)
  945.         {
  946.             emsg2((char_u *)"ml_get: cannot find line %ld", (char_u *)lnum);
  947.             goto errorret;
  948.         }
  949.  
  950.         dp = (DATA_BL *)(hp->bh_data);
  951.  
  952.         ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK);
  953.         buf->b_ml.ml_line_ptr = ptr;
  954.         buf->b_ml.ml_line_lnum = lnum;
  955.         buf->b_ml.ml_flags &= ~ML_LINE_DIRTY;
  956.     }
  957.     if (will_change)
  958.         buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  959.  
  960.     return buf->b_ml.ml_line_ptr;
  961. }
  962.  
  963. /*
  964.  * Check if a line that was just obtained by a call to ml_get
  965.  * is in allocated memory.
  966.  */
  967.     int
  968. ml_line_alloced()
  969. {
  970.     return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY);
  971. }
  972.  
  973. /*
  974.  * append a line after lnum (may be 0 to insert a line in front of the file)
  975.  *
  976.  *   newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum
  977.  *                will be set for recovery
  978.  *
  979.  * return FAIL for failure, OK otherwise
  980.  */
  981.     int
  982. ml_append(lnum, line, len, newfile)
  983.     linenr_t    lnum;            /* append after this line (can be 0) */
  984.     char_u        *line;            /* text of the new line */
  985.     colnr_t        len;            /* length of new line, including NUL, or 0 */
  986.     int            newfile;        /* flag, see above */
  987. {
  988.      if (curbuf->b_ml.ml_line_lnum != 0)
  989.         ml_flush_line(curbuf);
  990.     return ml_append_int(curbuf, lnum, line, len, newfile);
  991. }
  992.  
  993.     static int
  994. ml_append_int(buf, lnum, line, len, newfile)
  995.     BUF            *buf;
  996.     linenr_t    lnum;            /* append after this line (can be 0) */
  997.     char_u        *line;            /* text of the new line */
  998.     colnr_t        len;            /* length of line, including NUL, or 0 */
  999.     int            newfile;        /* flag, see above */
  1000. {
  1001.     int            i;
  1002.     int            line_count;        /* number of indexes in current block */
  1003.     int            offset;
  1004.     int            from, to;
  1005.     int            space_needed;    /* space needed for new line */
  1006.     int            page_size;
  1007.     int            page_count;
  1008.     int            db_idx;            /* index for lnum in data block */
  1009.     BHDR        *hp = NULL;
  1010.     BHDR        *hp2;
  1011.     MEMFILE        *mfp;
  1012.     DATA_BL        *dp;
  1013.     PTR_BL        *pp;
  1014.     IPTR        *ip;
  1015.  
  1016.     if (lnum > buf->b_ml.ml_line_count)    /* lnum out of range */
  1017.         return FAIL;
  1018.     
  1019.     if (lowest_marked && lowest_marked > lnum)
  1020.         lowest_marked = lnum + 1;
  1021.  
  1022.     if (len == 0)
  1023.         len = STRLEN(line) + 1;            /* space needed for the text */
  1024.     space_needed = len + INDEX_SIZE;    /* space needed for text + index */
  1025.  
  1026.     mfp = buf->b_ml.ml_mfp;
  1027.     page_size = mfp->mf_page_size;
  1028.  
  1029.      if (buf->b_ml.ml_flags & ML_EMPTY)            /* empty file */
  1030.     {
  1031. /*
  1032.  * Special case: Add first line to empty file.
  1033.  * Create the first data block.
  1034.  * If lnum == 0, line 1 is inserted below.
  1035.  * If lnum == 1, insert an empty line 1 and insert line 2 below.
  1036.  */
  1037.         /*
  1038.          * allocate the first data block
  1039.          */
  1040.         if (lnum == 1)                    /* reserve space for line 1 */
  1041.             space_needed += 1 + INDEX_SIZE;
  1042.         page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size;
  1043.         if ((hp = ml_new_data(mfp, newfile, page_count)) == NULL)
  1044.             return FAIL;
  1045.  
  1046.         if (lnum == 1)                    /* insert line 1 here, empty */
  1047.         {
  1048.             dp = (DATA_BL *)(hp->bh_data);
  1049.             dp->db_index[0] = --dp->db_txt_start;        /* at end of block */
  1050.             dp->db_free -= 1 + INDEX_SIZE;
  1051.             dp->db_line_count = 1;
  1052.             *((char_u *)dp + dp->db_txt_start) = NUL;    /* emtpy line */
  1053.             space_needed -= 1 + INDEX_SIZE;                /* space for line 1 */
  1054.         }
  1055.  
  1056.         /*
  1057.          * update the first pointer block
  1058.          */
  1059.         if ((hp2 = mf_get(mfp, (blocknr_t)1, 1)) == NULL)
  1060.         {
  1061.             mf_free(mfp, hp);
  1062.             return FAIL;
  1063.         }
  1064.         pp = (PTR_BL *)(hp2->bh_data);    /* must be pointer block */
  1065.         if (pp->pb_id != PTR_ID)
  1066.         {
  1067.             EMSG("pointer block id wrong 5");
  1068.             mf_free(mfp, hp);
  1069.             mf_put(mfp, hp2, FALSE, FALSE);
  1070.             return FAIL;
  1071.         }
  1072.         pp->pb_count = 1;
  1073.         pp->pb_pointer[0].pe_bnum = hp->bh_bnum;
  1074.         pp->pb_pointer[0].pe_page_count = page_count;
  1075.         pp->pb_pointer[0].pe_old_lnum = 1;
  1076.         pp->pb_pointer[0].pe_line_count = lnum + 1;        /* line count after insertion */
  1077.         mf_put(mfp, hp2, TRUE, FALSE);
  1078.  
  1079.         buf->b_ml.ml_flags &= ~ML_EMPTY;
  1080.         line_count = lnum;                /* 0 or 1 line in block before insertion */
  1081.         buf->b_ml.ml_line_count = lnum;
  1082.         db_idx = lnum - 1;                /* append new line after -1 or 0 */
  1083.     }
  1084.     else            /* not empty file */
  1085.     {
  1086. /*
  1087.  * find the data block containing the previous line
  1088.  * This also fills the stack with the blocks from the root to the data block
  1089.  * This also releases any locked block.
  1090.  */
  1091.         if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_t)1 : lnum, ML_INSERT)) == NULL)
  1092.             return FAIL;
  1093.  
  1094.         if (lnum == 0)                /* got line one instead, correct db_idx */
  1095.             db_idx = -1;            /* careful, it is negative! */
  1096.         else
  1097.             db_idx = lnum - buf->b_ml.ml_locked_low;
  1098.                     /* get line count before the insertion */
  1099.         line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
  1100.     }
  1101.  
  1102.     dp = (DATA_BL *)(hp->bh_data);
  1103.  
  1104. /*
  1105.  * If
  1106.  * - there is not enough room in the current block
  1107.  * - appending to the last line in the block
  1108.  * - not appending to the last line in the file
  1109.  * insert in front of the next block.
  1110.  */
  1111.     if ((int)dp->db_free < space_needed && db_idx == line_count - 1 &&
  1112.                                             lnum < buf->b_ml.ml_line_count)
  1113.     {
  1114.         /*
  1115.          * Now that the line is not going to be inserted in the block that we
  1116.          * expected, the line count has to be adjusted in the pointer blocks
  1117.          * by using ml_locked_lineadd.
  1118.          */
  1119.         --(buf->b_ml.ml_locked_lineadd);
  1120.         --(buf->b_ml.ml_locked_high);
  1121.         if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL)
  1122.             return FAIL;
  1123.  
  1124.         db_idx = -1;                /* careful, it is negative! */
  1125.                     /* get line count before the insertion */
  1126.         line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low;
  1127.         CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1");
  1128.  
  1129.         dp = (DATA_BL *)(hp->bh_data);
  1130.     }
  1131.  
  1132.     ++buf->b_ml.ml_line_count;
  1133.  
  1134.     if ((int)dp->db_free >= space_needed)        /* enough room in data block */
  1135.     {
  1136. /*
  1137.  * Insert new line in existing data block, or in data block allocated above.
  1138.  */
  1139.         dp->db_txt_start -= len;
  1140.         dp->db_free -= space_needed;
  1141.         ++(dp->db_line_count);
  1142.  
  1143.         /*
  1144.          * move the text of the lines that follow to the front
  1145.          * adjust the indexes of the lines that follow
  1146.          */
  1147.         if (line_count > db_idx + 1)        /* if there are following lines */
  1148.         {
  1149.             /*
  1150.              * Offset is the start of the previous line.
  1151.              * This will become the character just after the new line.
  1152.              */
  1153.             if (db_idx < 0)
  1154.                 offset = dp->db_txt_end;
  1155.             else
  1156.                 offset = ((dp->db_index[db_idx]) & DB_INDEX_MASK);
  1157.             memmove((char *)dp + dp->db_txt_start,
  1158.                             (char *)dp + dp->db_txt_start + len,
  1159.                             (size_t)(offset - (dp->db_txt_start + len)));
  1160.             for (i = line_count - 1; i > db_idx; --i)
  1161.                 dp->db_index[i + 1] = dp->db_index[i] - len;
  1162.             dp->db_index[db_idx + 1] = offset - len;
  1163.         }
  1164.         else                                /* add line at the end */
  1165.             dp->db_index[db_idx + 1] = dp->db_txt_start;
  1166.  
  1167.         /*
  1168.          * copy the text into the block
  1169.          */
  1170.         memmove((char *)dp + dp->db_index[db_idx + 1], (char *)line, (size_t)len);
  1171.  
  1172.         /*
  1173.          * Mark the block dirty.
  1174.          */
  1175.         buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1176.         if (!newfile)
  1177.             buf->b_ml.ml_flags |= ML_LOCKED_POS;
  1178.     }
  1179.     else            /* not enough space in data block */
  1180.     {
  1181. /*
  1182.  * If there is not enough room we have to create a new data block and copy some
  1183.  * lines into it.
  1184.  * Then we have to insert an entry in the pointer block.
  1185.  * If this pointer block also is full, we go up another block, and so on, up
  1186.  * to the root if necessary.
  1187.  * The line counts in the pointer blocks have already been adjusted by
  1188.  * ml_find_line().
  1189.  */
  1190.         int            line_count_left, line_count_right;
  1191.         int            page_count_left, page_count_right;
  1192.         BHDR        *hp_left;
  1193.         BHDR        *hp_right;
  1194.         BHDR        *hp_new;
  1195.         int            lines_moved;
  1196.         int            data_moved = 0;            /* init to shut up gcc */
  1197.         int            total_moved = 0;        /* init to shut up gcc */
  1198.         DATA_BL        *dp_right, *dp_left;
  1199.         int            stack_idx;
  1200.         int            in_left;
  1201.         int            lineadd;
  1202.         blocknr_t    bnum_left, bnum_right;
  1203.         linenr_t    lnum_left, lnum_right;
  1204.         int            pb_idx;
  1205.         PTR_BL        *pp_new;
  1206.  
  1207.         /*
  1208.          * We are going to allocate a new data block. Depending on the situation
  1209.          * it will be put to the left or right of the existing block.
  1210.          * If possible we put the new line in the left block and move the
  1211.          * lines after it to the right block. Otherwise the new line is also put
  1212.          * in the right block. This method is more efficient when inserting a lot
  1213.          * of lines at one place.
  1214.          */
  1215.         if (db_idx < 0)            /* left block is new, right block is existing */
  1216.         {
  1217.             lines_moved = 0;
  1218.             in_left = TRUE;
  1219.             /* space_needed does not change */
  1220.         }
  1221.         else                    /* left block is existing, right block is new */
  1222.         {
  1223.             lines_moved = line_count - db_idx - 1;
  1224.             if (lines_moved == 0)
  1225.                 in_left = FALSE;        /* put new line in right block */
  1226.                                         /* space_needed does not change */
  1227.             else
  1228.             {
  1229.                 data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) - dp->db_txt_start;
  1230.                 total_moved = data_moved + lines_moved * INDEX_SIZE;
  1231.                 if ((int)dp->db_free + total_moved >= space_needed)
  1232.                 {
  1233.                     in_left = TRUE;        /* put new line in left block */
  1234.                     space_needed = total_moved;
  1235.                 }
  1236.                 else
  1237.                 {
  1238.                     in_left = FALSE;        /* put new line in right block */
  1239.                     space_needed += total_moved;
  1240.                 }
  1241.             }
  1242.         }
  1243.  
  1244.         page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size;
  1245.         if ((hp_new = ml_new_data(mfp, newfile, page_count)) == 0)
  1246.         {
  1247.                         /* correct line counts in pointer blocks */
  1248.             --(buf->b_ml.ml_locked_lineadd);
  1249.             --(buf->b_ml.ml_locked_high);
  1250.             return FAIL;
  1251.         }
  1252.         if (db_idx < 0)            /* left block is new */
  1253.         {
  1254.             hp_left = hp_new;
  1255.             hp_right = hp;
  1256.             line_count_left = 0;
  1257.             line_count_right = line_count;
  1258.         }
  1259.         else                    /* right block is new */
  1260.         {
  1261.             hp_left = hp;
  1262.             hp_right = hp_new;
  1263.             line_count_left = line_count;
  1264.             line_count_right = 0;
  1265.         }
  1266.         dp_right = (DATA_BL *)(hp_right->bh_data);
  1267.         dp_left = (DATA_BL *)(hp_left->bh_data);
  1268.         bnum_left = hp_left->bh_bnum;
  1269.         bnum_right = hp_right->bh_bnum;
  1270.         page_count_left = hp_left->bh_page_count;
  1271.         page_count_right = hp_right->bh_page_count;
  1272.  
  1273.         /*
  1274.          * May move the new line into the right/new block.
  1275.          */
  1276.         if (!in_left)
  1277.         {
  1278.             dp_right->db_txt_start -= len;
  1279.             dp_right->db_free -= len + INDEX_SIZE;
  1280.             dp_right->db_index[0] = dp_right->db_txt_start;
  1281.             memmove((char *)dp_right + dp_right->db_txt_start, (char *)line, (size_t)len);
  1282.             ++line_count_right;
  1283.         }
  1284.         /*
  1285.          * may move lines from the left/old block to the right/new one.
  1286.          */
  1287.         if (lines_moved)
  1288.         {
  1289.             /*
  1290.              */
  1291.             dp_right->db_txt_start -= data_moved;
  1292.             dp_right->db_free -= total_moved;
  1293.             memmove((char *)dp_right + dp_right->db_txt_start,
  1294.                                 (char *)dp_left + dp_left->db_txt_start,
  1295.                                 (size_t)data_moved);
  1296.             offset = dp_right->db_txt_start - dp_left->db_txt_start;
  1297.             dp_left->db_txt_start += data_moved;
  1298.             dp_left->db_free += total_moved;
  1299.  
  1300.             /*
  1301.              * update indexes in the new block
  1302.              */
  1303.             for (to = line_count_right, from = db_idx + 1; from < line_count_left; ++from, ++to)
  1304.                 dp_right->db_index[to] = dp->db_index[from] + offset;
  1305.             line_count_right += lines_moved;
  1306.             line_count_left -= lines_moved;
  1307.         }
  1308.  
  1309.         /*
  1310.          * May move the new line into the left (old or new) block.
  1311.          */
  1312.         if (in_left)
  1313.         {
  1314.             dp_left->db_txt_start -= len;
  1315.             dp_left->db_free -= len + INDEX_SIZE;
  1316.             dp_left->db_index[line_count_left] = dp_left->db_txt_start;
  1317.             memmove((char *)dp_left + dp_left->db_txt_start, (char *)line,
  1318.                                         (size_t)len);
  1319.             ++line_count_left;
  1320.         }
  1321.  
  1322.         if (db_idx < 0)            /* left block is new */
  1323.         {
  1324.             lnum_left = lnum + 1;
  1325.             lnum_right = 0;
  1326.         }
  1327.         else                    /* right block is new */
  1328.         {
  1329.             lnum_left = 0;
  1330.             if (in_left)
  1331.                 lnum_right = lnum + 2;
  1332.             else
  1333.                 lnum_right = lnum + 1;
  1334.         }
  1335.         dp_left->db_line_count = line_count_left;
  1336.         dp_right->db_line_count = line_count_right;
  1337.  
  1338.         /*
  1339.          * release the two data blocks
  1340.          * The new one (hp_new) already has a correct blocknumber.
  1341.          * The old one (hp, in ml_locked) gets a positive blocknumber if
  1342.          * we changed it and we are not editing a new file.
  1343.          */
  1344.         if (lines_moved || in_left)
  1345.             buf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1346.         if (!newfile && db_idx >= 0 && in_left)
  1347.             buf->b_ml.ml_flags |= ML_LOCKED_POS;
  1348.         mf_put(mfp, hp_new, TRUE, FALSE);
  1349.  
  1350.         /*
  1351.          * flush the old data block
  1352.          * set ml_locked_lineadd to 0, because the updating of the
  1353.          * pointer blocks is done below
  1354.          */
  1355.         lineadd = buf->b_ml.ml_locked_lineadd;
  1356.         buf->b_ml.ml_locked_lineadd = 0;
  1357.         ml_find_line(buf, (linenr_t)0, ML_FLUSH);    /* flush data block */
  1358.  
  1359.         /*
  1360.          * update pointer blocks for the new data block
  1361.          */
  1362.         for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx)
  1363.         {
  1364.             ip = &(buf->b_ml.ml_stack[stack_idx]);
  1365.             pb_idx = ip->ip_index;
  1366.             if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  1367.                 return FAIL;
  1368.             pp = (PTR_BL *)(hp->bh_data);    /* must be pointer block */
  1369.             if (pp->pb_id != PTR_ID)
  1370.             {
  1371.                 EMSG("pointer block id wrong 3");
  1372.                 mf_put(mfp, hp, FALSE, FALSE);
  1373.                 return FAIL;
  1374.             }
  1375.             /*
  1376.              * TODO: If the pointer block is full and we are adding at the end
  1377.              * try to insert in front of the next block
  1378.              */
  1379.             if (pp->pb_count < pp->pb_count_max)    /* block not full, add one entry */
  1380.             {
  1381.                 if (pb_idx + 1 < (int)pp->pb_count)
  1382.                     memmove((char *)&pp->pb_pointer[pb_idx + 2],
  1383.                                 (char *)&pp->pb_pointer[pb_idx + 1],
  1384.                                 (size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN));
  1385.                 ++pp->pb_count;
  1386.                 pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
  1387.                 pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
  1388.                 pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
  1389.                 pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
  1390.                 pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
  1391.                 pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
  1392.  
  1393.                 if (lnum_left != 0)
  1394.                     pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
  1395.                 if (lnum_right != 0)
  1396.                     pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
  1397.  
  1398.                 mf_put(mfp, hp, TRUE, FALSE);
  1399.                 buf->b_ml.ml_stack_top = stack_idx + 1;        /* truncate stack */
  1400.  
  1401.                 if (lineadd)
  1402.                 {
  1403.                     --(buf->b_ml.ml_stack_top);
  1404.                         /* fix line count for rest of blocks in the stack */
  1405.                     ml_lineadd(buf, lineadd);
  1406.                                                         /* fix stack itself */
  1407.                     buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += lineadd;
  1408.                     ++(buf->b_ml.ml_stack_top);
  1409.                 }
  1410.  
  1411.                 return OK;
  1412.             }
  1413.             else                        /* pointer block full */
  1414.             {
  1415.                 /*
  1416.                  * split the pointer block
  1417.                  * allocate a new pointer block
  1418.                  * move some of the pointer into the new block
  1419.                  * prepare for updating the parent block
  1420.                  */
  1421.                 for (;;)        /* do this twice when splitting block 1 */
  1422.                 {
  1423.                     hp_new = ml_new_ptr(mfp);
  1424.                     if (hp_new == NULL)        /* TODO: try to fix tree */
  1425.                         return FAIL;
  1426.                     pp_new = (PTR_BL *)(hp_new->bh_data);
  1427.  
  1428.                     if (hp->bh_bnum != 1)
  1429.                         break;
  1430.  
  1431.                     /*
  1432.                      * if block 1 becomes full the tree is given an extra level
  1433.                      * The pointers from block 1 are moved into the new block.
  1434.                      * block 1 is updated to point to the new block
  1435.                      * then continue to split the new block
  1436.                      */
  1437.                     memmove((char *)pp_new, (char *)pp, (size_t)page_size);
  1438.                     pp->pb_count = 1;
  1439.                     pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum;
  1440.                     pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count;
  1441.                     pp->pb_pointer[0].pe_old_lnum = 1;
  1442.                     pp->pb_pointer[0].pe_page_count = 1;
  1443.                     mf_put(mfp, hp, TRUE, FALSE);    /* release block 1 */
  1444.                     hp = hp_new;                    /* new block is to be split */
  1445.                     pp = pp_new;
  1446.                     CHECK(stack_idx != 0, "stack_idx should be 0");
  1447.                     ip->ip_index = 0;
  1448.                     ++stack_idx;        /* do block 1 again later */
  1449.                 }
  1450.                 /*
  1451.                  * move the pointers after the current one to the new block
  1452.                  * If there are none, the new entry will be in the new block.
  1453.                  */
  1454.                 total_moved = pp->pb_count - pb_idx - 1;
  1455.                 if (total_moved)
  1456.                 {
  1457.                     memmove((char *)&pp_new->pb_pointer[0],
  1458.                                 (char *)&pp->pb_pointer[pb_idx + 1],
  1459.                                 (size_t)(total_moved) * sizeof(PTR_EN));
  1460.                     pp_new->pb_count = total_moved;
  1461.                     pp->pb_count -= total_moved - 1;
  1462.                     pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right;
  1463.                     pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right;
  1464.                     pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right;
  1465.                     if (lnum_right)
  1466.                         pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right;
  1467.                 }
  1468.                 else
  1469.                 {
  1470.                     pp_new->pb_count = 1;
  1471.                     pp_new->pb_pointer[0].pe_bnum = bnum_right;
  1472.                     pp_new->pb_pointer[0].pe_line_count = line_count_right;
  1473.                     pp_new->pb_pointer[0].pe_page_count = page_count_right;
  1474.                     pp_new->pb_pointer[0].pe_old_lnum = lnum_right;
  1475.                 }
  1476.                 pp->pb_pointer[pb_idx].pe_bnum = bnum_left;
  1477.                 pp->pb_pointer[pb_idx].pe_line_count = line_count_left;
  1478.                 pp->pb_pointer[pb_idx].pe_page_count = page_count_left;
  1479.                 if (lnum_left)
  1480.                     pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left;
  1481.                 lnum_left = 0;
  1482.                 lnum_right = 0;
  1483.  
  1484.                 /*
  1485.                  * recompute line counts
  1486.                  */
  1487.                 line_count_right = 0;
  1488.                 for (i = 0; i < (int)pp_new->pb_count; ++i)
  1489.                     line_count_right += pp_new->pb_pointer[i].pe_line_count;
  1490.                 line_count_left = 0;
  1491.                 for (i = 0; i < (int)pp->pb_count; ++i)
  1492.                     line_count_left += pp->pb_pointer[i].pe_line_count;
  1493.  
  1494.                 bnum_left = hp->bh_bnum;
  1495.                 bnum_right = hp_new->bh_bnum;
  1496.                 page_count_left = 1;
  1497.                 page_count_right = 1;
  1498.                 mf_put(mfp, hp, TRUE, FALSE);
  1499.                 mf_put(mfp, hp_new, TRUE, FALSE);
  1500.             }
  1501.         }
  1502.         EMSG("Updated too many blocks?");
  1503.         buf->b_ml.ml_stack_top = 0;        /* invalidate stack */
  1504.     }
  1505.     return OK;
  1506. }
  1507.  
  1508. /*
  1509.  * replace line lnum, with buffering, in current buffer
  1510.  *
  1511.  * If copy is TRUE, make a copy of the line, otherwise the line has been
  1512.  * copied to allocated memory already.
  1513.  *
  1514.  * return FAIL for failure, OK otherwise
  1515.  */
  1516.     int
  1517. ml_replace(lnum, line, copy)
  1518.     linenr_t    lnum;
  1519.     char_u        *line;
  1520.     int            copy;
  1521. {
  1522.     int            status;
  1523.  
  1524.     if (line == NULL)            /* just checking... */
  1525.         return FAIL;
  1526.  
  1527.     /*
  1528.      * if empty file simply append the one and only line
  1529.      */
  1530.     if (curbuf->b_ml.ml_flags & ML_EMPTY)
  1531.     {
  1532.         if (*line == NUL)        /* nothing to do */
  1533.             return OK;
  1534.         status = ml_append_int(curbuf, lnum - 1, line, (colnr_t)0, FALSE);
  1535.         if (!copy)
  1536.             free(line);
  1537.         return status;
  1538.     }
  1539.  
  1540.     /*
  1541.      * if only line replaced by empty line, buffer becomes empty
  1542.      */
  1543.     if (lnum == 1 && *line == NUL && curbuf->b_ml.ml_line_count == 1)
  1544.     {
  1545.         status = ml_delete(lnum);
  1546.         if (!copy)
  1547.             free(line);
  1548.         return status;
  1549.     }
  1550.  
  1551.     if (curbuf->b_ml.ml_line_lnum != lnum)        /* other line currently buffered */
  1552.         ml_flush_line(curbuf);                    /* flush it */
  1553.     else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY)    /* same line has been allocated */
  1554.         free(curbuf->b_ml.ml_line_ptr);            /* free it */
  1555.     if (copy && (line = strsave(line)) == NULL)    /* allocate memory for the line */
  1556.         return FAIL;
  1557.     curbuf->b_ml.ml_line_ptr = line;
  1558.     curbuf->b_ml.ml_line_lnum = lnum;
  1559.     curbuf->b_ml.ml_flags |= ML_LINE_DIRTY;
  1560.  
  1561.     return OK;
  1562. }
  1563.  
  1564. /*
  1565.  * delete line 'lnum'
  1566.  *
  1567.  * return FAIL for failure, OK otherwise
  1568.  */
  1569.     int
  1570. ml_delete(lnum)
  1571.     linenr_t    lnum;
  1572. {
  1573.     ml_flush_line(curbuf);
  1574.     return ml_delete_int(curbuf, lnum);
  1575. }
  1576.  
  1577.     static int
  1578. ml_delete_int(buf, lnum)
  1579.     BUF            *buf;
  1580.     linenr_t    lnum;
  1581. {
  1582.     BHDR    *hp;
  1583.     MEMFILE    *mfp;
  1584.     DATA_BL    *dp;
  1585.     PTR_BL    *pp;
  1586.     IPTR    *ip;
  1587.     int        count;            /* number of entries in block */
  1588.     int        idx;
  1589.     int        stack_idx;
  1590.     int        text_start;
  1591.     int        line_start;
  1592.     int        line_size;
  1593.     int        i;
  1594.  
  1595.     if (lnum < 1 || lnum > buf->b_ml.ml_line_count)
  1596.         return FAIL;
  1597.  
  1598.     if (lowest_marked && lowest_marked > lnum)
  1599.         lowest_marked--;
  1600.  
  1601.     if (buf->b_ml.ml_flags & ML_EMPTY)            /* nothing to delete */
  1602.         return FAIL;
  1603.  
  1604.     /*
  1605.      * find the data block containing the line
  1606.      * This also fills the stack with the blocks from the root to the data block
  1607.      * This also releases any locked block.
  1608.      */
  1609.     mfp = buf->b_ml.ml_mfp;
  1610.  
  1611.     if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL)
  1612.         return FAIL;
  1613.  
  1614.     dp = (DATA_BL *)(hp->bh_data);
  1615.             /* compute line count before the delete */
  1616.     count = (long)(buf->b_ml.ml_locked_high) - (long)(buf->b_ml.ml_locked_low) + 2;
  1617.     idx = lnum - buf->b_ml.ml_locked_low;
  1618.  
  1619. /*
  1620.  * If the file becomes empty the data block is freed.
  1621.  * The pointer blocks will be updated when the first line is appended.
  1622.  */
  1623.     if (--buf->b_ml.ml_line_count == 0)        /* file becomes empty */
  1624.     {
  1625.         CHECK(count != 1, "ml_delete: count not 1");
  1626.         CHECK(idx != 0, "ml_delete: idx not 0");
  1627.         buf->b_ml.ml_line_count = 1;
  1628.         buf->b_ml.ml_flags |= ML_EMPTY;
  1629.         mf_free(mfp, hp);                        /* free the data block */
  1630.         buf->b_ml.ml_locked = NULL;
  1631.         buf->b_ml.ml_stack_top = 0;                /* flush stack */
  1632.         return OK;
  1633.     }
  1634.  
  1635. /*
  1636.  * special case: If there is only one line in the data block it becomes empty.
  1637.  * Then we have to remove the entry, pointing to this data block, from the
  1638.  * pointer block. If this pointer block also becomes empty, we go up another
  1639.  * block, and so on, up to the root if necessary.
  1640.  * The line counts in the pointer blocks have already been adjusted by
  1641.  * ml_find_line().
  1642.  */
  1643.     if (count == 1)
  1644.     {
  1645.         mf_free(mfp, hp);        /* free the data block */
  1646.         buf->b_ml.ml_locked = NULL;
  1647.  
  1648.         for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx)
  1649.         {
  1650.             buf->b_ml.ml_stack_top = 0;        /* stack is invalid when failing */
  1651.             ip = &(buf->b_ml.ml_stack[stack_idx]);
  1652.             idx = ip->ip_index;
  1653.             if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  1654.                 return FAIL;
  1655.             pp = (PTR_BL *)(hp->bh_data);    /* must be pointer block */
  1656.             if (pp->pb_id != PTR_ID)
  1657.             {
  1658.                 EMSG("pointer block id wrong 4");
  1659.                 mf_put(mfp, hp, FALSE, FALSE);
  1660.                 return FAIL;
  1661.             }
  1662.             count = --(pp->pb_count);
  1663.             if (count == 0)            /* the pointer block becomes empty! */
  1664.                 mf_free(mfp, hp);
  1665.             else
  1666.             {
  1667.                 if (count != idx)        /* move entries after the deleted one */
  1668.                     memmove((char *)&pp->pb_pointer[idx],
  1669.                                 (char *)&pp->pb_pointer[idx + 1],
  1670.                                 (size_t)(count - idx) * sizeof(PTR_EN));
  1671.                 mf_put(mfp, hp, TRUE, FALSE);
  1672.  
  1673.                 buf->b_ml.ml_stack_top = stack_idx;        /* truncate stack */
  1674.                     /* fix line count for rest of blocks in the stack */
  1675.                 if (buf->b_ml.ml_locked_lineadd)
  1676.                 {
  1677.                     ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
  1678.                     buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
  1679.                                                 buf->b_ml.ml_locked_lineadd;
  1680.                 }
  1681.                 ++(buf->b_ml.ml_stack_top);
  1682.  
  1683.                 return OK;
  1684.             }
  1685.         }
  1686.         CHECK(1, "deleted block 1?");
  1687.  
  1688.         return OK;
  1689.     }
  1690.  
  1691.     /*
  1692.      * delete the text by moving the next lines forwards
  1693.      */
  1694.     text_start = dp->db_txt_start;
  1695.     line_start = ((dp->db_index[idx]) & DB_INDEX_MASK);
  1696.     if (idx == 0)                /* first line in block, text at the end */
  1697.         line_size = dp->db_txt_end - line_start;
  1698.     else
  1699.         line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start;
  1700.     memmove((char *)dp + text_start + line_size, (char *)dp + text_start,
  1701.                             (size_t)(line_start - text_start));
  1702.  
  1703.     /*
  1704.      * delete the index by moving the next indexes backwards
  1705.      * Adjust the indexes for the text movement.
  1706.      */
  1707.     for (i = idx; i < count - 1; ++i)
  1708.         dp->db_index[i] = dp->db_index[i + 1] + line_size;
  1709.  
  1710.     dp->db_free += line_size + INDEX_SIZE;
  1711.     dp->db_txt_start += line_size;
  1712.     --(dp->db_line_count);
  1713.  
  1714.     /*
  1715.      * mark the block dirty and make sure it is in the file (for recovery)
  1716.      */
  1717.     buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  1718.  
  1719.     return OK;
  1720. }
  1721.  
  1722. /*
  1723.  * set the B_MARKED flag for line 'lnum'
  1724.  */
  1725.     void
  1726. ml_setmarked(lnum)
  1727.     linenr_t lnum;
  1728. {
  1729.     BHDR    *hp;
  1730.     DATA_BL    *dp;
  1731.  
  1732.     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)        /* invalid line number */
  1733.         return;                /* give error message? */
  1734.  
  1735.     if (lowest_marked == 0 || lowest_marked > lnum)
  1736.         lowest_marked = lnum;
  1737.  
  1738.     /*
  1739.      * find the data block containing the line
  1740.      * This also fills the stack with the blocks from the root to the data block
  1741.      * This also releases any locked block.
  1742.      */
  1743.     if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  1744.         return;                /* give error message? */
  1745.  
  1746.     dp = (DATA_BL *)(hp->bh_data);
  1747.     dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED;
  1748.     curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1749. }
  1750.  
  1751. /*
  1752.  * find the first line with its B_MARKED flag set
  1753.  */
  1754.     linenr_t
  1755. ml_firstmarked()
  1756. {
  1757.     BHDR        *hp;
  1758.     DATA_BL        *dp;
  1759.     linenr_t    lnum;
  1760.     int            i;
  1761.  
  1762.     /*
  1763.      * The search starts with lowest_marked line. This is the last line where
  1764.      * a mark was found, adjusted by inserting/deleting lines.
  1765.      */
  1766.     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
  1767.     {
  1768.         /*
  1769.          * Find the data block containing the line.
  1770.          * This also fills the stack with the blocks from the root to the data block
  1771.          * This also releases any locked block.
  1772.          */
  1773.         if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  1774.             return (linenr_t)0;                /* give error message? */
  1775.  
  1776.         dp = (DATA_BL *)(hp->bh_data);
  1777.  
  1778.         for (i = lnum - curbuf->b_ml.ml_locked_low;
  1779.                             lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
  1780.             if ((dp->db_index[i]) & DB_MARKED)
  1781.             {
  1782.                 (dp->db_index[i]) &= DB_INDEX_MASK;
  1783.                 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1784.                 lowest_marked = lnum + 1;
  1785.                 return lnum;
  1786.             }
  1787.     }
  1788.  
  1789.     return (linenr_t) 0;
  1790. }
  1791.  
  1792. /*
  1793.  * return TRUE if line 'lnum' has a mark
  1794.  */
  1795.     int
  1796. ml_has_mark(lnum)
  1797.     linenr_t    lnum;
  1798. {
  1799.     BHDR        *hp;
  1800.     DATA_BL        *dp;
  1801.  
  1802.     if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  1803.         return FALSE;
  1804.  
  1805.     dp = (DATA_BL *)(hp->bh_data);
  1806.     return (int)((dp->db_index[lnum - curbuf->b_ml.ml_locked_low]) & DB_MARKED);
  1807. }
  1808.  
  1809. /*
  1810.  * clear all DB_MARKED flags
  1811.  */
  1812.     void
  1813. ml_clearmarked()
  1814. {
  1815.     BHDR        *hp;
  1816.     DATA_BL        *dp;
  1817.     linenr_t    lnum;
  1818.     int            i;
  1819.  
  1820.     /*
  1821.      * The search starts with line lowest_marked.
  1822.      */
  1823.     for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; )
  1824.     {
  1825.         /*
  1826.          * Find the data block containing the line.
  1827.          * This also fills the stack with the blocks from the root to the data block
  1828.          * This also releases any locked block.
  1829.          */
  1830.         if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL)
  1831.             return;                /* give error message? */
  1832.  
  1833.         dp = (DATA_BL *)(hp->bh_data);
  1834.  
  1835.         for (i = lnum - curbuf->b_ml.ml_locked_low;
  1836.                             lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum)
  1837.             if ((dp->db_index[i]) & DB_MARKED)
  1838.             {
  1839.                 (dp->db_index[i]) &= DB_INDEX_MASK;
  1840.                 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY;
  1841.             }
  1842.     }
  1843.  
  1844.     lowest_marked = 0;
  1845.     return;
  1846. }
  1847.  
  1848. /*
  1849.  * flush ml_line if necessary
  1850.  */
  1851.     static void
  1852. ml_flush_line(buf)
  1853.     BUF        *buf;
  1854. {
  1855.     BHDR        *hp;
  1856.     DATA_BL        *dp;
  1857.     linenr_t    lnum;
  1858.     char_u        *new_line;
  1859.     char_u        *old_line;
  1860.     colnr_t        new_len;
  1861.     int            old_len;
  1862.     int            extra;
  1863.     int            idx;
  1864.     int            start;
  1865.     int            count;
  1866.     int            i;
  1867.  
  1868.      if (buf->b_ml.ml_line_lnum == 0)        /* nothing to do */
  1869.         return;
  1870.  
  1871.     if (buf->b_ml.ml_flags & ML_LINE_DIRTY)
  1872.     {
  1873.         lnum = buf->b_ml.ml_line_lnum;
  1874.         new_line = buf->b_ml.ml_line_ptr;
  1875.  
  1876.         hp = ml_find_line(buf, lnum, ML_FIND);
  1877.         if (hp == NULL)
  1878.             EMSG2("Cannot fine line %ld", (char_u *)lnum);
  1879.         else
  1880.         {
  1881.             dp = (DATA_BL *)(hp->bh_data);
  1882.             idx = lnum - buf->b_ml.ml_locked_low;
  1883.             start = ((dp->db_index[idx]) & DB_INDEX_MASK);
  1884.             old_line = (char_u *)dp + start;
  1885.             if (idx == 0)        /* line is last in block */
  1886.                 old_len = dp->db_txt_end - start;
  1887.             else                /* text of previous line follows */
  1888.                 old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
  1889.             new_len = STRLEN(new_line) + 1;
  1890.             extra = new_len - old_len;        /* negative if lines gets smaller */
  1891.  
  1892.             /*
  1893.              * if new line fits in data block, replace directly
  1894.              */
  1895.             if ((int)dp->db_free >= extra)
  1896.             {
  1897.                     /* if the length changes and there are following lines */
  1898.                 count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1;
  1899.                 if (extra != 0 && idx < count - 1)
  1900.                 {
  1901.                         /* move text of following lines */
  1902.                     memmove((char *)dp + dp->db_txt_start - extra,
  1903.                                 (char *)dp + dp->db_txt_start,
  1904.                                 (size_t)(start - dp->db_txt_start));
  1905.  
  1906.                         /* adjust pointers of this and following lines */
  1907.                     for (i = idx + 1; i < count; ++i)
  1908.                         dp->db_index[i] -= extra;
  1909.                 }
  1910.                 dp->db_index[idx] -= extra;
  1911.  
  1912.                     /* adjust free space */
  1913.                 dp->db_free -= extra;
  1914.                 dp->db_txt_start -= extra;
  1915.  
  1916.                     /* copy new line into the data block */
  1917.                 memmove((char *)old_line - extra, (char *)new_line, (size_t)new_len);
  1918.                 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS);
  1919.             }
  1920.             else
  1921.             {
  1922.                 /*
  1923.                  * Cannot do it in one data block: delete and append.
  1924.                  */
  1925.                     /* How about handling errors??? */
  1926.                 (void)ml_delete_int(buf, lnum);
  1927.                 (void)ml_append_int(buf, lnum - 1, new_line, new_len, FALSE);
  1928.             }
  1929.         }
  1930.         free(new_line);
  1931.     }
  1932.  
  1933.     buf->b_ml.ml_line_lnum = 0;
  1934. }
  1935.  
  1936. /*
  1937.  * create a new, empty, data block
  1938.  */
  1939.     static BHDR *
  1940. ml_new_data(mfp, negative, page_count)
  1941.     MEMFILE        *mfp;
  1942.     int            negative;
  1943.     int            page_count;
  1944. {
  1945.     BHDR        *hp;
  1946.     DATA_BL        *dp;
  1947.  
  1948.     if ((hp = mf_new(mfp, negative, page_count)) == NULL)
  1949.         return NULL;
  1950.     
  1951.     dp = (DATA_BL *)(hp->bh_data);
  1952.     dp->db_id = DATA_ID;
  1953.     dp->db_txt_start = dp->db_txt_end = page_count * mfp->mf_page_size;
  1954.     dp->db_free = dp->db_txt_start - HEADER_SIZE;
  1955.     dp->db_line_count = 0;
  1956.  
  1957.     return hp;
  1958. }
  1959.  
  1960. /*
  1961.  * create a new, empty, pointer block
  1962.  */
  1963.     static BHDR *
  1964. ml_new_ptr(mfp)
  1965.     MEMFILE        *mfp;
  1966. {
  1967.     BHDR        *hp;
  1968.     PTR_BL        *pp;
  1969.  
  1970.     if ((hp = mf_new(mfp, FALSE, 1)) == NULL)
  1971.         return NULL;
  1972.     
  1973.     pp = (PTR_BL *)(hp->bh_data);
  1974.     pp->pb_id = PTR_ID;
  1975.     pp->pb_count = 0;
  1976.     pp->pb_count_max = (mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1;
  1977.  
  1978.     return hp;
  1979. }
  1980.  
  1981. /*
  1982.  * lookup line 'lnum' in a memline
  1983.  *
  1984.  *   action: if ML_DELETE or ML_INSERT the line count is updated while searching
  1985.  *             if ML_FLUSH only flush a locked block
  1986.  *             if ML_FIND just find the line
  1987.  *
  1988.  * If the block was found it is locked and put in ml_locked.
  1989.  * The stack is updated to lead to the locked block. The ip_high field in
  1990.  * the stack is updated to reflect the last line in the block AFTER the
  1991.  * insert or delete, also if the pointer block has not been updated yet. But
  1992.  * if if ml_locked != NULL ml_locked_lineadd must be added to ip_high.
  1993.  *
  1994.  * return: NULL for failure, pointer to block header otherwise
  1995.  */
  1996.     static BHDR *
  1997. ml_find_line(buf, lnum, action)
  1998.     BUF            *buf;
  1999.     linenr_t    lnum;
  2000.     int            action;
  2001. {
  2002.     DATA_BL        *dp;
  2003.     PTR_BL        *pp;
  2004.     IPTR        *ip;
  2005.     BHDR        *hp;
  2006.     MEMFILE        *mfp;
  2007.     linenr_t    t;
  2008.     blocknr_t    bnum, bnum2;
  2009.     int            dirty;
  2010.     linenr_t    low, high;
  2011.     int            top;
  2012.     int            page_count;
  2013.     int            idx;
  2014.  
  2015.     mfp = buf->b_ml.ml_mfp;
  2016.  
  2017.     /*
  2018.      * If there is a locked block check if the wanted line is in it.
  2019.      * If not, flush and release the locked block.
  2020.      * Don't do this for ML_INSERT_SAME, because the stack need to be updated.
  2021.      * Don't do this for ML_FLUSH, because we want to flush the locked block.
  2022.      */
  2023.     if (buf->b_ml.ml_locked)
  2024.     {
  2025.         if (ML_SIMPLE(action) && buf->b_ml.ml_locked_low <= lnum &&
  2026.                                     buf->b_ml.ml_locked_high >= lnum)
  2027.         {
  2028.                 /* remember to update pointer blocks and stack later */
  2029.             if (action == ML_INSERT)
  2030.             {
  2031.                 ++(buf->b_ml.ml_locked_lineadd);
  2032.                 ++(buf->b_ml.ml_locked_high);
  2033.             }
  2034.             else if (action == ML_DELETE)
  2035.             {
  2036.                 --(buf->b_ml.ml_locked_lineadd);
  2037.                 --(buf->b_ml.ml_locked_high);
  2038.             }
  2039.             return (buf->b_ml.ml_locked);
  2040.         }
  2041.  
  2042.         mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY,
  2043.                                             buf->b_ml.ml_flags & ML_LOCKED_POS);
  2044.         buf->b_ml.ml_locked = NULL;
  2045.  
  2046.             /*
  2047.              * if lines have been added or deleted in the locked block, need to
  2048.              * update the line count in pointer blocks
  2049.              */
  2050.         if (buf->b_ml.ml_locked_lineadd)
  2051.             ml_lineadd(buf, buf->b_ml.ml_locked_lineadd);
  2052.     }
  2053.  
  2054.     if (action == ML_FLUSH)            /* nothing else to do */
  2055.         return NULL;
  2056.  
  2057.     bnum = 1;                        /* start at the root of the tree */
  2058.     page_count = 1;
  2059.     low = 1;
  2060.     high = buf->b_ml.ml_line_count;
  2061.  
  2062.     if (action == ML_FIND)        /* first try stack entries */
  2063.     {
  2064.         for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top)
  2065.         {
  2066.             ip = &(buf->b_ml.ml_stack[top]);
  2067.             if (ip->ip_low <= lnum && ip->ip_high >= lnum)
  2068.             {
  2069.                 bnum = ip->ip_bnum;
  2070.                 low = ip->ip_low;
  2071.                 high = ip->ip_high;
  2072.                 buf->b_ml.ml_stack_top = top;    /* truncate stack at prev entry */
  2073.                 break;
  2074.             }
  2075.         }
  2076.         if (top < 0)
  2077.             buf->b_ml.ml_stack_top = 0;            /* not found, start at the root */
  2078.     }
  2079.     else        /* ML_DELETE or ML_INSERT */
  2080.         buf->b_ml.ml_stack_top = 0;        /* start at the root */
  2081.  
  2082. /*
  2083.  * search downwards in the tree until a data block is found
  2084.  */
  2085.     for (;;)
  2086.     {
  2087.         if ((hp = mf_get(mfp, bnum, page_count)) == NULL)
  2088.             goto error_noblock;
  2089.  
  2090.         /*
  2091.          * update high for insert/delete
  2092.          */
  2093.         if (action == ML_INSERT)
  2094.             ++high;
  2095.         else if (action == ML_DELETE)
  2096.             --high;
  2097.  
  2098.         dp = (DATA_BL *)(hp->bh_data);
  2099.         if (dp->db_id == DATA_ID)        /* data block */
  2100.         {
  2101.             buf->b_ml.ml_locked = hp;
  2102.             buf->b_ml.ml_locked_low = low;
  2103.             buf->b_ml.ml_locked_high = high;
  2104.             buf->b_ml.ml_locked_lineadd = 0;
  2105.             buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS);
  2106.             return hp;
  2107.         }
  2108.  
  2109.         pp = (PTR_BL *)(dp);            /* must be pointer block */
  2110.         if (pp->pb_id != PTR_ID)
  2111.         {
  2112.             EMSG("pointer block id wrong");
  2113.             goto error_block;
  2114.         }
  2115.  
  2116.         if ((top = ml_add_stack(buf)) < 0)        /* add new entry to stack */
  2117.             goto error_block;
  2118.         ip = &(buf->b_ml.ml_stack[top]);
  2119.         ip->ip_bnum = bnum;
  2120.         ip->ip_low = low;
  2121.         ip->ip_high = high;
  2122.         ip->ip_index = -1;                /* index not known yet */
  2123.  
  2124.         dirty = FALSE;
  2125.         for (idx = 0; idx < (int)pp->pb_count; ++idx)
  2126.         {
  2127.             t = pp->pb_pointer[idx].pe_line_count;
  2128.             CHECK(t == 0, "pe_line_count is zero");
  2129.             if ((low += t) > lnum)
  2130.             {
  2131.                 ip->ip_index = idx;
  2132.                 bnum = pp->pb_pointer[idx].pe_bnum;
  2133.                 page_count = pp->pb_pointer[idx].pe_page_count;
  2134.                 high = low - 1;
  2135.                 low -= t;
  2136.  
  2137.                 /*
  2138.                  * a negative block number may have been changed
  2139.                  */
  2140.                 if (bnum < 0)
  2141.                 {
  2142.                     bnum2 = mf_trans_del(mfp, bnum);
  2143.                     if (bnum != bnum2)
  2144.                     {
  2145.                         bnum = bnum2;
  2146.                         pp->pb_pointer[idx].pe_bnum = bnum;
  2147.                         dirty = TRUE;
  2148.                     }
  2149.                 }
  2150.  
  2151.                 break;
  2152.             }
  2153.         }
  2154.         if (idx >= (int)pp->pb_count)        /* past the end: something wrong! */
  2155.         {
  2156.             if (lnum > buf->b_ml.ml_line_count)
  2157.                 emsg2((char_u *)"line number out of range: %ld past the end", (char_u *)(lnum - buf->b_ml.ml_line_count));
  2158.  
  2159.             else
  2160.                 emsg2((char_u *)"line count wrong in block %ld", (char_u *)(bnum));
  2161.             goto error_block;
  2162.         }
  2163.         if (action == ML_DELETE)
  2164.         {
  2165.             pp->pb_pointer[idx].pe_line_count--;
  2166.             dirty = TRUE;
  2167.         }
  2168.         else if (action == ML_INSERT)
  2169.         {
  2170.             pp->pb_pointer[idx].pe_line_count++;
  2171.             dirty = TRUE;
  2172.         }
  2173.         mf_put(mfp, hp, dirty, FALSE);
  2174.     }
  2175.  
  2176. error_block:
  2177.     mf_put(mfp, hp, FALSE, FALSE);
  2178. error_noblock:
  2179. /*
  2180.  * If action is ML_DELETE or ML_INSERT we have to correct the tree for
  2181.  * the incremented/decremented line counts, because there won't be a line
  2182.  * inserted/deleted after all.
  2183.  */
  2184.     if (action == ML_DELETE)
  2185.         ml_lineadd(buf, 1);
  2186.     else if (action == ML_INSERT)
  2187.         ml_lineadd(buf, -1);
  2188.     buf->b_ml.ml_stack_top = 0;
  2189.     return NULL;
  2190. }
  2191.  
  2192. /*
  2193.  * add an entry to the info pointer stack
  2194.  *
  2195.  * return -1 for failure, number of the new entry otherwise
  2196.  */
  2197.     static int
  2198. ml_add_stack(buf)
  2199.     BUF        *buf;
  2200. {
  2201.     int        top;
  2202.     IPTR    *newstack;
  2203.  
  2204.     top = buf->b_ml.ml_stack_top;
  2205.  
  2206.         /* may have to increase the stack size */
  2207.     if (top == buf->b_ml.ml_stack_size)
  2208.     {
  2209.         CHECK(top > 0, "Stack size increases");    /* more than 5 levels??? */
  2210.  
  2211.         newstack = (IPTR *)alloc((unsigned)sizeof(IPTR) * (buf->b_ml.ml_stack_size + STACK_INCR));
  2212.         if (newstack == NULL)
  2213.             return -1;
  2214.         memmove((char *)newstack, (char *)buf->b_ml.ml_stack, (size_t)top * sizeof(IPTR));
  2215.         free(buf->b_ml.ml_stack);
  2216.         buf->b_ml.ml_stack = newstack;
  2217.         buf->b_ml.ml_stack_size += STACK_INCR;
  2218.     }
  2219.  
  2220.     buf->b_ml.ml_stack_top++;
  2221.     return top;
  2222. }
  2223.  
  2224. /*
  2225.  * Update the pointer blocks on the stack for inserted/deleted lines.
  2226.  * The stack itself is also updated.
  2227.  *
  2228.  * When a insert/delete line action fails, the line is not inserted/deleted,
  2229.  * but the pointer blocks have already been updated. That is fixed here by
  2230.  * walking through the stack.
  2231.  *
  2232.  * Count is the number of lines added, negative if lines have been deleted.
  2233.  */
  2234.     static void
  2235. ml_lineadd(buf, count)
  2236.     BUF            *buf;
  2237.     int            count;
  2238. {
  2239.     int            idx;
  2240.     IPTR        *ip;
  2241.     PTR_BL        *pp;
  2242.     MEMFILE        *mfp = buf->b_ml.ml_mfp;
  2243.     BHDR        *hp;
  2244.  
  2245.     for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx)
  2246.     {
  2247.         ip = &(buf->b_ml.ml_stack[idx]);
  2248.         if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL)
  2249.             break;
  2250.         pp = (PTR_BL *)(hp->bh_data);    /* must be pointer block */
  2251.         if (pp->pb_id != PTR_ID)
  2252.         {
  2253.             mf_put(mfp, hp, FALSE, FALSE);
  2254.             EMSG("pointer block id wrong 2");
  2255.             break;
  2256.         }
  2257.         pp->pb_pointer[ip->ip_index].pe_line_count += count;
  2258.         ip->ip_high += count;
  2259.         mf_put(mfp, hp, TRUE, FALSE);
  2260.     }
  2261. }
  2262.  
  2263. /*
  2264.  * make swap file name out of the filename
  2265.  */
  2266.     static char_u *
  2267. makeswapname(buf, second_try)
  2268.     BUF        *buf;
  2269.     int        second_try;
  2270. {
  2271.     char_u        *r, *s, *fname;
  2272.     char_u        *pdir;
  2273.  
  2274.     r = modname(curbuf->b_xfilename, (char_u *)".swp");
  2275.     /*
  2276.      * do not try to use 'directory' option
  2277.      * - if 'directory' option not set
  2278.      * - if out of memory
  2279.      * - not a second try and 'directory' option does not start with '>'
  2280.      */
  2281.     if (*p_dir == NUL || r == NULL || (!second_try && *p_dir != '>'))
  2282.         return r;
  2283.  
  2284.     fname = gettail(r);
  2285.     if (*p_dir == '>')            /* skip '>' in front of dir name */
  2286.         pdir = p_dir + 1;
  2287.     else
  2288.         pdir = p_dir;
  2289.     s = alloc((unsigned)(STRLEN(pdir) + STRLEN(fname) + 2));
  2290.     if (s != NULL)
  2291.     {
  2292.         STRCPY(s, pdir);
  2293.         if (*s && !ispathsep(*(s + STRLEN(s) - 1)))    /* don't add '/' after ':' */
  2294.             STRCAT(s, PATHSEPSTR);
  2295.         STRCAT(s, fname);
  2296.     }
  2297.     free(r);
  2298.     return s;
  2299. }
  2300.  
  2301. /*
  2302.  * Find out what name to use for the swap file for buffer 'buf'.
  2303.  *
  2304.  * Several names are tried to find one that does not exist
  2305.  */
  2306.     static char_u *
  2307. findswapname(buf, second_try)
  2308.     BUF        *buf;
  2309.     int        second_try;
  2310. {
  2311.     char_u        *fname;
  2312.     int            n;
  2313.  
  2314. #ifdef AMIGA
  2315.     int            r;
  2316.     BPTR        fh;
  2317.     FILE        *dummyfd = NULL;
  2318.  
  2319. /*
  2320.  * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS
  2321.  * compatible filesystem, it is possible that the file "test.doc.swp" which we
  2322.  * create will be exactly the same file. To avoid this problem we temporarily
  2323.  * create "test.doc".
  2324.  */
  2325.     if (!(buf->b_p_sn || buf->b_shortname) && buf->b_xfilename &&
  2326.                                             getperm(buf->b_xfilename) < 0)
  2327.         dummyfd = fopen((char *)buf->b_xfilename, "w");
  2328. #endif
  2329.  
  2330. /*
  2331.  * we try different names until we find one that does not exist yet
  2332.  */
  2333.     fname = makeswapname(buf, second_try);
  2334.     for (;;)
  2335.     {
  2336.         if (fname == NULL)        /* must be out of memory */
  2337.             break;
  2338.         if ((n = STRLEN(fname)) == 0)    /* safety check */
  2339.         {
  2340.             free(fname);
  2341.             fname = NULL;
  2342.             break;
  2343.         }
  2344.         
  2345.         /*
  2346.          * check if the scriptfile already exists
  2347.          */
  2348.         if (getperm(fname) < 0)        /* it does not exist */
  2349.         {
  2350. #ifdef AMIGA
  2351.             fh = Open((UBYTE *)fname, (long)MODE_NEWFILE);
  2352.             /*
  2353.              * on the Amiga getperm() will return -1 when the file exists but
  2354.              * is being used by another program. This happens if you edit
  2355.              * a file twice.
  2356.              */
  2357.             if (fh != (BPTR)NULL)        /* can open file, OK */
  2358.             {
  2359.                 Close(fh);
  2360.                 break;
  2361.             }
  2362.             if (IoErr() != ERROR_OBJECT_IN_USE && IoErr() != ERROR_OBJECT_EXISTS)
  2363. #endif
  2364.                 break;
  2365.         }
  2366.     /*
  2367.      * get here when file already exists
  2368.      */
  2369.         if (fname[n - 1] == 'p')        /* first try */
  2370.         {
  2371. #ifdef AMIGA
  2372.         /*
  2373.          * on MS-DOS compatible filesystems (e.g. messydos) file.doc.swp
  2374.          * and file.doc are the same file. To guess if this problem is
  2375.          * present try if file.doc.swx exists. If it does, we set
  2376.          * buf->b_shortname and try file_doc.swp (dots replaced by
  2377.          * underscores for this file), and try again. If it doesn't we
  2378.          * assume that "file.doc.swp" already exists.
  2379.          */
  2380.             if (!(buf->b_p_sn || buf->b_shortname))        /* not tried yet */
  2381.             {
  2382.                 fname[n - 1] = 'x';
  2383.                 r = getperm(fname);    /* try "file.swx" */
  2384.                 fname[n - 1] = 'p';
  2385.                 if (r >= 0)                    /* it seems to exist */
  2386.                 {
  2387.                     buf->b_shortname = TRUE;
  2388.                     free(fname);
  2389.                     fname = makeswapname(buf, second_try);    /* '.' replaced by '_' */
  2390.                     continue;                        /* try again */
  2391.                 }
  2392.             }
  2393. #endif
  2394.             /*
  2395.              * If we get here ".swp" file really exists.
  2396.              * Give an error message, unless recovering or no file name.
  2397.              */
  2398.             if (!recoverymode && buf->b_xfilename != NULL)
  2399.             {
  2400.                         /* call wait_return if not done by emsg() */
  2401.                 if (EMSG2(".swp file exists: An edit of file \"%s\" may not have been finished", buf->b_xfilename))
  2402.                 {
  2403.                     msg_outchar('\n');
  2404.                     wait_return(FALSE);        /* do call wait_return now */
  2405.                 }
  2406.             }
  2407.         }
  2408.  
  2409.         if (fname[n - 1] == 'a')    /* tried enough names, give up */
  2410.         {
  2411.             free(fname);
  2412.             fname = NULL;
  2413.             break;
  2414.         }
  2415.         --fname[n - 1];                /* change last char of the name */
  2416.     }
  2417.  
  2418. #ifdef AMIGA
  2419.     if (dummyfd)        /* file has been created temporarily */
  2420.     {
  2421.         fclose(dummyfd);
  2422.         remove((char *)buf->b_xfilename);
  2423.     }
  2424. #endif
  2425.     return fname;
  2426. }
  2427.